
/*
   Assembler with relocation option-addressing symbols with PC relative
   addressing mode.
*/

#include"hexdec.cpp"
#include"source.cpp"
#include"optbedit.cpp"
class sym
{  char symbol[10];
   char addr[5];
   int left,right;
   public:
   sym()
   {
   left=0;
   right=0;
   }
   void setsymbol(char* x)
   {
    strcpy(symbol,x);
   }
   void setaddr(char *x)
   {
    strcpy(addr,x);
   }
   void setleft(int x)
   { left=x;
   }
   void setright(int x)
   { right=x;
   }
   char* retsymbol()
   { return symbol;
   }
   char* retaddr()
   { return addr;
   }
   int retleft()
   { return left;}
   int retright()
   { return right; }

   void outdata(int i)
    {
    gotoxy(2,i+4);
    cout<<symbol;
    gotoxy(18,i+4);
    cout<<addr;
    }
}; // end of class

void addsym(sym nu)             // add an object to the symtab
{
 sym root,t,temp;
 int j,n;
 static int i=0;
 int ptr,prev;
 fstream os;


  os.open("symtab.dat",ios::in|ios::out|ios::binary);
  os.seekg(0,ios::beg);
  os.read((char*)&root,sizeof(root));
  if(root.retleft()==0)
    {
     i++;
     os.seekp(1*sizeof(sym),ios::beg);
     os.write((char*)&nu,sizeof(nu));
     os.seekg(0,ios::beg);
     os.read((char*)&t,sizeof(t));
     temp.setsymbol(" ");
     temp.setaddr(" ");
     temp.setleft(1);
     temp.setright(0);
     os.seekp(0,ios::beg);
     os.write((char*)&temp,sizeof(temp));
    }//end of if
   else
    { ptr=1;
      i++;
      while(ptr!=0)
       { os.seekg(ptr*sizeof(sym),ios::beg);
		 os.read((char*)&t,sizeof(t));
		 prev=ptr;
		if(strcmpi(nu.retsymbol(),t.retsymbol()) <= 0 )
		 { ptr=t.retleft(); }
		else
		 {ptr=t.retright(); }

	   }  // end of while
	  if(strcmpi(nu.retsymbol(),t.retsymbol()) <= 0 )
	   { os.seekp(i*sizeof(sym),ios::beg);
		 os.write((char*)&nu,sizeof(nu));
		 os.seekg(prev*sizeof(sym),ios::beg);
		 os.read((char*)&t,sizeof(t));
		 temp.setsymbol(t.retsymbol());
		 temp.setaddr(t.retaddr());
		 temp.setleft(i);
		 temp.setright(t.retright());
		 os.seekp(prev*sizeof(sym),ios::beg);
		 os.write((char*)&temp,sizeof(temp));
	   }
	 else
	  { os.seekp(i*sizeof(sym),ios::beg);
		os.write((char*)&nu,sizeof(nu));
		os.seekg(prev*sizeof(sym),ios::beg);
		os.read((char*)&t,sizeof(t));
		temp.setsymbol(t.retsymbol());
		temp.setaddr(t.retaddr());
		temp.setleft(t.retleft());
		temp.setright(i);
		os.seekp(prev*sizeof(sym),ios::beg);
		os.write((char*)&temp,sizeof(temp));
	   }
	}// end of else
	os.close();
}

int searchsym(char str[])      // search the symbol table
{ifstream os;
 sym t;
 int temp,ptr=1;
 os.open("symtab.dat",ios::in|ios::binary);
 os.seekg(0,ios::beg);
 os.read((char*)&t,sizeof(t));
 if(t.retleft()==0)
 {
   os.close();
   return 0;
 }

 while(ptr!=0)
 { os.seekg(ptr*sizeof(sym),ios::beg);
   os.read((char*)&t,sizeof(t));
   if(strcmpi(str,t.retsymbol()) < 0)
     {
      ptr=t.retleft();
     }
   else if(strcmpi(str,t.retsymbol()) == 0)
     {
      strcpy(str,t.retaddr());
      os.close();
      return 1;
      }
    else
     {
      ptr=t.retright();
     }

 }  // end of while loop

   return 0;

} // end of search

void pass1()                        // pass1
{
 sym root,t;       //object of symtab
 oprec  op;        // object of source file
 ifstream sfile;   // source file pointer
 int i,j,n;
 char locctr[10],staddr[10],temp[10];
 char length[10];

 sfile.open("source.dat",ios::in|ios::binary);
 sfile.read((char*)&op,sizeof(op));
 if(strcmpi(op.retmnemonic(),"start")==0)
 {
  strcpy(staddr,op.retoperand());
  strcpy(locctr,op.retoperand());
  sfile.read((char*)&op,sizeof(op));
 }
 else
 {
 strcpy(locctr,"0");
 }
 while(strcmpi(op.retmnemonic(),"end"))
 {
  if(strcmpi(op.retlabel(),"/")!=0)
   {
	 strcpy(temp,op.retlabel());
	 if(searchsym(temp)==0)
	{
	 root.setsymbol(op.retlabel());
	 root.setaddr(locctr);
	 addsym(root);
	}
	  else
	{
	 cout<<"Duplicate label"<<op.retlabel();
	 getch();
	 exit(0);
	}
   }// end of if search label
   strcpy(temp,op.retmnemonic());
   // search for opcode
   if(searchop(temp)!=0)
   {
	n=3;
	hex(locctr,'+',n);
   }
   else if(strcmpi(temp,"word")==0)
   {
	n=3;
	hex(locctr,'+',n);
   }
   else if(strcmpi(temp,"resw")==0)
   {
	n=atoi(op.retoperand());
	n*=3;
	hex(locctr,'+',n);
   }
   else if(strcmpi(temp,"byte")==0)
   {
	n=strlen(op.retoperand());
	n-=3;
	hex(locctr,'+',n);
   }
   else if(strcmpi(temp,"resb")==0)
   {
	n=atoi(op.retoperand());
	hex(locctr,'+',n);
   }
   else
   { cout<<" Error...";
	 getch();
	 exit(0);
	}
   sfile.read((char*)&op,sizeof(op));

 }// end of while loop

 n=atoi(staddr);
 strcpy(length,locctr);
 hex(length,'-',n);
}// end of pass1

void pass2()
{
 sym root,t;    //object of symtab
 outrec out;    // object of outfile
 oprec  op;        // object of source file
 ifstream sfile;   // source file pointer
 ofstream ofile;   // outfile pointer
 int i,j,n,len,len1;
 char locctr[10],taddr[10],tempop[10];
 char temp[10],tempsym[10];
 ofile.open("outfile1.dat",ios::out|ios::binary);


 sfile.open("source.dat",ios::in|ios::binary);
 sfile.read((char*)&op,sizeof(op));
 if(strcmpi(op.retmnemonic(),"start")==0)
 {
  out.setlabel(op.retlabel());
  out.setmnemonic(op.retmnemonic());
  out.setoperand(op.retoperand());
  strcpy(locctr,op.retoperand());

  out.setobjcode("000000");
  ofile.write((char*)&out,sizeof(out));

  sfile.read((char*)&op,sizeof(op));
 }
 while(strcmpi(op.retmnemonic(),"end"))
 {
  // search optab for opcode
  strcpy(tempop,op.retmnemonic());
  if(searchop(tempop)!=0)
  {
   n=3;
   hex(locctr,'+',n);

   n=3;
   hex(tempop,'+',n);
   if(strlen(tempop)==1)
   {
	strcpy(temp,"0");
	strcat(temp,tempop);
	strcpy(tempop,temp);
   }
   if(strcmpi(op.retoperand(),"/")!=0)
	 {

	  strcpy(tempsym,op.retoperand());
	  if(searchsym(tempsym)!=0)
	   {
		strcpy(taddr,tempsym);
		len=0;
		hex(locctr,'+',len);
		hex(tempsym,'-',len);
		int l=strlen(tempsym);
		if(l==3)
		{ strcpy(temp,"2");
		  strcat(temp,tempsym);
		  strcpy(tempsym,temp);
		 }
		else if(l==2)
		{ strcpy(temp,"20");
		  strcat(temp,tempsym);
		  strcpy(tempsym,temp);
		 }
		else if(l==1)
		{ strcpy(temp,"200");
		  strcat(temp,tempsym);
		  strcpy(tempsym,temp);
		 }
		else if((l==4)&&(tempsym[0]=='f'))
		{
		 tempsym[0]='2';
		}
		else
		{
		  strcpy(temp,"10");
		  strcat(temp,taddr);
		  strcpy(tempsym,temp);
		}

		strcat(tempop,tempsym);
		out.setlabel(op.retlabel());
		out.setmnemonic(op.retmnemonic());
		out.setoperand(op.retoperand());
		out.setobjcode(tempop);
		ofile.write((char*)&out,sizeof(out));
	   }
	  else
	   {
		cout<<"undefined symbol"<<op.retoperand();
		getch();
		exit(0);
	   }

	 }
	 else
	 {
	  out.setlabel(op.retlabel());
	  out.setmnemonic(op.retmnemonic());
	  out.setoperand(op.retoperand());
	  strcat(tempop,"0000");
	  out.setobjcode(tempop);
	  ofile.write((char*)&out,sizeof(out));
	 }// end of if /

  }// end of if optab

  else if(strcmpi(tempop,"word")==0)
  {
   n=atoi(op.retoperand());
   strcpy(tempop,"0000");
   hex(tempop,'+',n);
   char temp[10];
   int l=strlen(tempop);
   if(l==4)
   {
	strcpy(temp,"00");
   }
   else if(l==3)
   {
	strcpy(temp,"000");
   }
   else if(l==2)
   {
	strcpy(temp,"0000");
   }
   else if(l==1)
   {
	strcpy(temp,"00000");
   }

   strcat(temp,tempop);

   out.setlabel(op.retlabel());
   out.setmnemonic(op.retmnemonic());
   out.setoperand(op.retoperand());
   out.setobjcode(temp);
   ofile.write((char*)&out,sizeof(out));

   n=3;
   hex(locctr,'+',n);

  }
  else if(strcmpi(temp,"resw")==0)
   {
	n=atoi(op.retoperand());
	n*=3;
	hex(locctr,'+',n);
   }
  else if(strcmpi(temp,"resb")==0)
   {
	n=atoi(op.retoperand());
	hex(locctr,'+',n);
   }

  else if(strcmpi(tempop,"byte")==0)
  {
   char t[10];
   strcpy(t,op.retoperand());
   int l=strlen(t);
	  for(i=2;i<l-1;i++)
	   {tempsym[i-2]=t[i];}

	   tempsym[l-3]='\0';
	   out.setlabel(op.retlabel());
	   out.setmnemonic(op.retmnemonic());
	   out.setoperand(op.retoperand());
	   out.setobjcode(tempsym);
	   ofile.write((char*)&out,sizeof(out));
	n=strlen(op.retoperand());
	n-=3;
	hex(locctr,'+',n);

  }// end of if-else-if

   sfile.read((char*)&op,sizeof(op));

 }// end of while loop
   out.setlabel(op.retlabel());
   out.setmnemonic(op.retmnemonic());
   out.setoperand(op.retoperand());
   out.setobjcode("");
   ofile.write((char*)&out,sizeof(out));
   sfile.close();
   ofile.close();

}//end of pass2
void main()
{
ifstream stab,ofile;
ofstream s;
sym t;
outrec o;
int i=0,j=0;
clrscr();
// following is necessary to keep the root node

s.open("symtab.dat",ios::out|ios::binary);
t.setsymbol(" ");
t.setaddr(" ");
t.setleft(0);
t.setright(0);
s.write((char*)&t,sizeof(t));
s.close();


pass1();

cout<<"  SYMBOL TABLE ENTRIES\n";
stab.open("symtab.dat",ios::in|ios::binary);
while(!stab.eof())
 { stab.read((char*)&t,sizeof(t));
  if(!stab.eof())
   {t.outdata(i);
	i++;
	}
 }
stab.close();
cout<<"\n Press any key to continue...";
getch();

pass2();
clrscr();
 cout<<"------------------------------------------------";
 cout<<"\n LABEL      MNEMONIC       OPERAND     OBJCODE";
 cout<<"\n------------------------------------------------";

 i=0;

ofile.open("outfile1.dat",ios::in|ios::binary);
while(!ofile.eof())
 { ofile.read((char*)&o,sizeof(o));

  if(!ofile.eof())
   {o.display(i);
	i++;
	if(i==19)
	   {
	 i=0;
	 getch();
	 clrscr();
	 cout<<"------------------------------------------------";
	 cout<<"\n LABEL      MNEMONIC       OPERAND     OBJCODE";
	 cout<<"\n------------------------------------------------";

	   }
   }
 }
ofile.close();
cout<<"\n------------------------------------------------";

getch();

}